package oceanlife;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;

import javax.swing.JLabel;
import javax.swing.SwingWorker;

import oceanlife.evostrat.Gene;
import oceanlife.evostrat.GeneCrossing;
import oceanlife.evostrat.GenePillarHallway;
import oceanlife.log.Logger;
import oceanlife.pathfinding.Pillar;
import oceanlife.pathfinding.Pnt;


public class GenStarterWorker extends SwingWorker<Integer, Integer>{
		protected ArrayList<SimpleSimPanel> simPanels;
		protected ArrayList<AgentCustomSettings> agentSpawns;
		protected JLabel info;


		public GenStarterWorker(ArrayList<SimpleSimPanel> simPanels, ArrayList<AgentCustomSettings> agentSpawns, JLabel info) {
			this.agentSpawns = agentSpawns;
			this.simPanels = simPanels;
			this.info = info;
		}

		protected Integer doInBackground() throws Exception
        {
			ArrayList<ArrayList<ArrayList<Agent>>> agentScenarios = new ArrayList<ArrayList<ArrayList<Agent>>>();
			ArrayList<Pnt> agentScenarioGoals = new ArrayList<Pnt>();

			Gene gene = null;
			if(OLSet.get("testSet").equals("Straight")){		
				gene = GenePillarHallway.getInitChild();
			} else if(OLSet.get("testSet").equals("Crossing")){
				gene = GeneCrossing.getInitChild();
			}
			generateAgents(agentSpawns,agentScenarios,agentScenarioGoals);
			int generations = 0;
			Date dateNow = new Date ();
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd...HH_mm_ss.SSS");
			StringBuilder dateString = new StringBuilder( sdf.format( dateNow ) );
			Logger.write("Started_at: "+dateString.toString());
			Logger.write("Seed: "+RandomGen.getSeed());
			Logger.write("Testset: "+OLSet.get("testSet"));
			Logger.write("Agent_spawn_interval: "+OLSet.getInt("spawnInterval"));
			Logger.write("Scenario_count: "+OLSet.getInt("scenarioCount"));
			Logger.write("Children_count: "+OLSet.getInt("children"));
			Logger.write("Agents_per_Scenario: "+OLSet.getInt("agentsPerScenario"));
			while(OLSet.getInt("stopping") != 1){
				ArrayList<GenWorker> genWorkers = new ArrayList<GenWorker>();
				int IDCounter = 1;
	    		for(SimpleSimPanel simPanel : simPanels){
	    			simPanel.addAgentScenarios(agentScenarios,agentScenarioGoals);
	    			RandomGen rand = RandomGen.getNextRandomGen();
	    			dateNow = new Date();
	    			dateString = new StringBuilder( sdf.format( dateNow ) );
	    			String ID = OLSet.get("testSet")+"-"+OLSet.getInt("spawnInterval")+"-"+dateString.toString()+"-"+IDCounter;
	    			simPanel.readGenes(gene,rand,ID,true);
		            GenWorker gw = new GenWorker(simPanel);
		            genWorkers.add(gw);
		            gw.execute();
		            IDCounter++;
	    		}
	    		boolean running = true;
	    		while(running){
	    			running = false;
	    			for(GenWorker gw : genWorkers){
	    				if(!gw.isDone()){
	    					running = true;
	    					Thread.sleep(100);
	    					break;
	    				}
	    			}
	    		}
	    		generations++;
	    		if(OLSet.getInt("stopping") != 1){
	    			Logger.write("Generation: "+generations);
		    		SimpleSimPanel bestChild = simPanels.get(0);
		    		int agentNum = 1;
		    		for(SimpleSimPanel simPanel : simPanels){
		    			if(bestChild.getTotalAgentCycles() > simPanel.getTotalAgentCycles()){
		    				bestChild = simPanel;
		    			}
		    			Logger.write("Child: fitness "+simPanel.getTotalAgentCycles()+" stepsize "+simPanel.getGenes().getStepSizes()[0]);
		    			agentNum++;
		    		}
		    		gene = bestChild.getGenes();

		    		Logger.write("Best_Child: fitness "+bestChild.getTotalAgentCycles()+" stepsize "+bestChild.getGenes().getStepSizes()[0]);
		    		Logger.write(gene.printGenes());
		    		info.setText(Integer.toString(bestChild.getTotalAgentCycles()));
	    		}
			}
			dateNow = new Date ();
			sdf = new SimpleDateFormat("yyyy.MM.dd 'at' HH:mm:ss z");
			dateString = new StringBuilder( sdf.format( dateNow ) );
			Logger.write("Stopped_at: "+dateString.toString());
    		Logger.write("");
    		Logger.write("");
			return 0;
        }

		
		public void generateAgents(ArrayList<AgentCustomSettings> agentSpawns, ArrayList<ArrayList<ArrayList<Agent>>> agentScenarios, ArrayList<Pnt> agentScenarioGoals){			
			try {
				agentScenarios.clear();
				RandomGen randAgInit = RandomGen.getNextRandomGen();
				this.info.setText("Generating Agents:");
				//simPanel.setAgents(agents);
				AgentGenerator aG = new AgentGenerator();
				for(int i = 0; i < OLSet.getInt("scenarioCount"); i++){
					ArrayList<ArrayList<Agent>> agentSide = new ArrayList<ArrayList<Agent>>();
					int colorCode = 0;
					for(AgentCustomSettings agSet : agentSpawns){
						ArrayList<Agent> agents = new ArrayList<Agent>();
						agentSide.add(agents);
						if (agSet.inUse()){
							agents.addAll(aG.generateAgents(agSet.getNumAgents(),agSet.getSpawnBox(),agSet.getGoal(),colorCode,randAgInit));
							colorCode++;
						}
					}
					agentScenarios.add(agentSide);
				}
				for(AgentCustomSettings agSet : agentSpawns){
					if (agSet.inUse()){
						agentScenarioGoals.add(agSet.getGoal());
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		protected void done()
        {
                try
                {
                }
                catch (Exception e)
                {
                        e.printStackTrace();
                }
        }


}